package com.heima.article.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.apis.wemedia.IWeMediaClient;
import com.heima.article.mapper.ApArticleMapper;
import com.heima.article.service.HotArticleService;
import com.heima.common.constants.ArticleConstants;
import com.heima.common.redis.CacheService;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.vo.HotArticleVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.pojos.WmChannel;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@Transactional
public class HotArticleServiceImpl implements HotArticleService {

    @Autowired
    private ApArticleMapper apArticleMapper;

    /**
     * 计算热点文章
     */
    @Override
    public void computeHotArticle() {
        //1.查询前五天的数据
        //拿到五天前的时间
        Date date = DateTime.now().minusDays(10).toDate();
        List<ApArticle> articleListByLast5days = apArticleMapper.findArticleListByLast5days(date);
        //2.计算文章分值
        List<HotArticleVo> hotArticleVos = computeHotArticle(articleListByLast5days);
        //3.为每个频道缓存:文章与频道匹配展示
        channelWithArticle(hotArticleVos);
    }

    @Autowired
    private IWeMediaClient weMediaClient;

    /**
     * 匹配热点文章与频道
     *
     * @param hotArticleVos
     */
    private void channelWithArticle(List<HotArticleVo> hotArticleVos) {
        //参数校验 feign远程调用查询所有频道
        ResponseResult res = weMediaClient.getChannels();
        if (res.getCode().equals(200)) {
            //res的data是SpringBoot的RestController返回的json数据;需要有alibaba.fastjson转换
            String jsonString = JSON.toJSONString(res.getData());
            //再转换为json对象,避免出错
            List<WmChannel> wmChannels = JSON.parseArray(jsonString, WmChannel.class);
            if (wmChannels != null && wmChannels.size() > 0) {
                //匹配每个频道的文章
                for (WmChannel wmChannel : wmChannels) {
                    List<HotArticleVo> hotArticleVoList = hotArticleVos.stream()
                            .filter(x -> x.getChannelId().equals(wmChannel.getId()))
                            .collect(Collectors.toList());
                    //给每个频道的热点文章按分值进行排序  存入redis
                    sortAndRedis(hotArticleVoList, ArticleConstants.HOT_ARTICLE_FIRST_PAGE + wmChannel.getId());
                }
            }
        }
        //给推荐数据设置分值排序
        sortAndRedis(hotArticleVos, ArticleConstants.HOT_ARTICLE_FIRST_PAGE + ArticleConstants.DEFAULT_TAG);
    }

    @Autowired
    private CacheService cacheService;

    /**
     * 给每个频道设置热点数据,并存入redis
     *
     * @param hotArticleVoList
     */
    private void sortAndRedis(List<HotArticleVo> hotArticleVoList, String s) {
        //参数校验
        if (hotArticleVoList != null && hotArticleVoList.size() > 0) {
            //数据处理:展示30条热点数据
            hotArticleVoList = hotArticleVoList.stream()
                    .sorted(Comparator.comparing(HotArticleVo::getScore)
                            .reversed()).collect(Collectors.toList());
            if (hotArticleVoList.size() > 30) {
                hotArticleVoList = hotArticleVoList.stream().limit(30).collect(Collectors.toList());
            }
            cacheService.set(s, JSON.toJSONString(hotArticleVoList));
        }
    }


    /**
     * 计算最近五天的文章分值
     *
     * @param apArticleList
     */
    private List<HotArticleVo> computeHotArticle(List<ApArticle> apArticleList) {
        List<HotArticleVo> list = new ArrayList<>();
        if (apArticleList != null & apArticleList.size() > 0) {
            for (ApArticle apArticle : apArticleList) {
                //遍历文章,计算单篇得分
                Integer score = scores(apArticle);
                HotArticleVo articleVo = new HotArticleVo();
                BeanUtils.copyProperties(apArticle, articleVo);
                articleVo.setScore(score);
                list.add(articleVo);
            }
        }
        return list;
    }


    /**
     * 计算单篇文章得分
     *
     * @param apArticle
     * @return
     */
    private Integer scores(ApArticle apArticle) {
        Integer score = 0;
        //参数校验
        //数据处理:加权计算规则
        if (apArticle.getLikes() != null) {
            //点赞
            score += apArticle.getLikes() * ArticleConstants.HOT_ARTICLE_LIKE_WEIGHT;
        }
        if (apArticle.getCollection() != null) {
            //收藏
            score += apArticle.getCollection() * ArticleConstants.HOT_ARTICLE_COLLECTION_WEIGHT;
        }
        if (apArticle.getComment() != null) {
            //评论
            score += apArticle.getComment() * ArticleConstants.HOT_ARTICLE_COMMENT_WEIGHT;
        }
        if (apArticle.getViews() != null) {
            //阅读
            score += apArticle.getViews();
        }
        return score;
    }
}
